#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/binary_info.h"
#include "hardware/spi.h"

#include "wizchip_conf.h"
#include "w5100s.h"
#include "w5100s_spi.h"
#include "socket.h"
#include "loopback.h"
#include "MQTTClient.h"
#include "mqtt_interface.h"
#include "dns.h"
#include "string.h"

#define SOCKET_ID 0
#define ETHERNET_BUF_MAX_SIZE (1024 * 2)

#define MQTT_SEND_BUFF_SIZE 2048
#define MQTT_RECV_BUFF_SIZE 2048

uint8_t mqtt_send_buff[MQTT_SEND_BUFF_SIZE] = {0};
uint8_t mqtt_recv_buff[MQTT_RECV_BUFF_SIZE] = {0};

typedef struct MQTTCONNECTION
{
    char mqttHostUrl[1024];
    int port;
    char clientid[1024];
    char username[1024];
    char passwd[1024];
    uint8_t server_ip[4];
    char pubtopic[255];
    char subtopic1[255];
    char subtopic2[255];
    int QOS;
} mqttconn;

mqttconn mqtt_params = {
    .server_ip = {106,15,229,25},
    .port = 1883,
    .clientid = "hxrzyBEzRJz.MQTT1|securemode=2,signmethod=hmacsha256,timestamp=1693294744773|",
    .username = "MQTT1&hxrzyBEzRJz",
    .passwd = "2d5e49f797c8830f40655dc6132b5ef9d22741eb63448663aad91166d8ebf044",
    .pubtopic = "/sys/hxrzyBEzRJz/MQTT1/thing/event/property/post",
    .subtopic1 = "/sys/hxrzyBEzRJz/MQTT1/thing/event/property/post",
    .subtopic2 = "/sys/hxrzyBEzRJz/MQTT1/thing/service/property/set",
    .QOS = 0,
};

unsigned char *data_ptr = NULL;

void network_init(void);

wiz_NetInfo net_info = {
    .mac = {0x00, 0x08, 0xdc, 0x16, 0xed, 0x2e},
    .ip = {192, 168, 124, 10},
    .sn = {255, 255, 255, 0},
    .gw = {192, 168, 124, 1},
    .dns = {8, 8, 8, 8},
    .dhcp = NETINFO_STATIC};
MQTTClient c = {0};
Network n = {0};
int connOK;

bool repeating_timer_callback(struct repeating_timer *t);
void mqtt_init(void);
void messageArrived(MessageData *md);
void keep_alive(void);
wiz_NetInfo get_info;
static uint8_t ethernet_buf[ETHERNET_BUF_MAX_SIZE] = {0,};
static uint8_t destip[4]={192, 168, 124, 1};
static uint16_t destport = 8080;
static uint16_t local_port =8000;
int main()                                                          
{   
	struct repeating_timer timer;
    stdio_init_all();
    sleep_ms(2000);
	wizchip_initialize();
	wizchip_setnetinfo(&net_info);
	print_network_information(net_info);
    add_repeating_timer_ms(1, repeating_timer_callback, NULL, &timer);
    mqtt_init();
    while(true)
    {
        // loopback_udpc(SOCKET_ID, ethernet_buf, destip, destport);
      	keep_alive();
        sleep_ms(10);
    }
    
}

bool repeating_timer_callback(struct repeating_timer *t)
{
    MilliTimer_Handler();
    return true;
}

void mqtt_init(void)
{
    int ret;

    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    NewNetwork(&n, 1);
    ConnectNetwork(&n, mqtt_params.server_ip, 1883);
    MQTTClientInit(&c, &n, 1000, mqtt_send_buff, MQTT_SEND_BUFF_SIZE, mqtt_recv_buff, MQTT_RECV_BUFF_SIZE);
    data.willFlag = 0;
    data.MQTTVersion = 3;
    data.clientID.cstring = mqtt_params.clientid;
    data.username.cstring = mqtt_params.username;
    data.password.cstring = mqtt_params.passwd;
    data.keepAliveInterval = 30;
    data.cleansession = 1;
    connOK = MQTTConnect(&c, &data);
    printf("Connected:%s\r\n", connOK == 0 ? "success" : "failed");
    printf("Subscribing to %s\r\n", mqtt_params.subtopic1);
    ret = MQTTSubscribe(&c, mqtt_params.subtopic1, mqtt_params.QOS, messageArrived);
    printf("Subscribed:%s\r\n", ret == 0 ? "success" : "failed");
    printf("Subscribing to %s\r\n", mqtt_params.subtopic2);
    ret = MQTTSubscribe(&c, mqtt_params.subtopic2, mqtt_params.QOS, messageArrived);
    printf("Subscribed:%s\r\n", ret == 0 ? "success" : "failed");
    sleep_ms(300);
    MQTTMessage pubmessage={
        .qos=QOS2,
        .dup=0,
        .retained=0,
        .id=0,
    };
    pubmessage.payload="hello mqtt!\r\n";
    pubmessage.payloadlen=strlen(pubmessage.payload);
    MQTTPublish(&c,mqtt_params.pubtopic,&pubmessage);
}

void messageArrived(MessageData* md)
{
	unsigned char messagebuffer[512];
	MQTTMessage* message = md->message;

	if (mqtt_params.QOS)
	{
		memcpy(messagebuffer,(char*)message->payload,(int)message->payloadlen);
		*(messagebuffer + (int)message->payloadlen + 1) = '\n';
		printf("%s\r\n",messagebuffer);
	}

	if (mqtt_params.QOS)
		printf("%.*s", (int)message->payloadlen, (char*)message->payload);
	else
		printf("%s%.*s%s", "RX:",(int)message->payloadlen, (char*)message->payload, mqtt_params.QOS);
}

void keep_alive(void)
{
    if (!connOK)
    {
        if (MQTTYield(&c, 30))
        {
            mqtt_init();
        }
    }
}


